package com.macrounion.atv.processor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.macrounion.atv.utils.MyPageUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.github.pagehelper.Page;
import com.google.common.collect.Lists;
import com.macrounion.atv.cache.AlarmCache;
import com.macrounion.atv.cache.CurrentDataCache;
import com.macrounion.atv.cache.DeviceIdQueue;
import com.macrounion.atv.service.entity.Channel;
import com.macrounion.atv.service.entity.CurrentData;
import com.macrounion.atv.service.entity.Device;
import com.macrounion.atv.service.entity.Spot;
import com.macrounion.atv.service.entity.ext.CurrentDataExt;
import com.macrounion.atv.service.service.CurrentDataService;
import com.macrounion.base.processor.BaseProcessor;
import com.macrounion.base.service.dto.PageRespDto;
import com.macrounion.base.service.entity.PageInfo;

@Component
@Transactional
public class CurrentDataProcessor extends BaseProcessor<CurrentData, CurrentData, CurrentDataService, CurrentData> {

    @Autowired
    private CurrentDataCache currentDataCache;

    @Autowired
    private ChannelProcessor channelProcessor;

    @Autowired
    private SpotProcessor spotProcessor;

    @Autowired
    private DeviceProcessor deviceProcessor;

    @Autowired
    private DeviceIdQueue deviceIdQueue;
    @Autowired
    private SaveCurrentDataProcessor saveCurrentDataProcessor;
    @Autowired
    private AlarmCache alarmCache;

    /**
     * 存储来自snmpGet的实时数据
     * type--->存储类型---实时数据/虚拟通道数据
     *
     * @param datas
     */
    public List<CurrentData> saveDataFromSnmp(String deviceId, List<CurrentData> datas, String type) {
        List<CurrentData> all = new ArrayList<>(datas);
        List<CurrentData> historys = all.parallelStream().filter(a -> {
            return a.getAlarm().equals(0);
        }).collect(Collectors.toList());
        List<CurrentData> alarms = all.parallelStream().filter(a -> {
            return a.getAlarm().equals(1);
        }).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(alarms)) {
            alarmCache.putAlarms(deviceId, alarms);
        }
        if (!CollectionUtils.isEmpty(historys)) {
            if (deviceIdQueue.has(deviceId + "-" + type)) {
                System.out.println(deviceId + "-" + type + "正在存储中。。。忽略此次更新");
                if (CollectionUtils.isEmpty(alarms))
                    return null;
            } else {
                deviceIdQueue.put(deviceId + "-" + type);
                return saveCurrentDataProcessor.saveData(deviceId, historys, type);
            }
        }
        return null;
    }

    /**
     * 存储报警数据
     * type--->存储类型---报警
     *
     * @param datas
     */
    public List<CurrentData> saveAlarmData(String deviceId, List<CurrentData> datas) {
        if (deviceIdQueue.has(deviceId + "-alarm")) {
            System.out.println(deviceId + "正在报警中。。。忽略此次更新");
            return null;
        }
        deviceIdQueue.put(deviceId + "-" + "-alarm");
        return saveCurrentDataProcessor.saveData(deviceId, new ArrayList<CurrentData>(datas), "-alarm");
    }

    /**
     * 获取有报警的数据列表
     *
     * @param request
     * @return
     */
    public List<CurrentDataExt> getAlarmList(CurrentDataExt request) {
        List<CurrentData> currentDataDestList = currentDataCache.getCurrentData(request.getDeviceId());
        List<CurrentData> currentDataList = new ArrayList<>(currentDataDestList);
        List<CurrentDataExt> resultList = new ArrayList<>();
        for (CurrentData currentData : currentDataList) {
            if (null != currentData.getAlarm() && 1 == currentData.getAlarm()) {
                CurrentDataExt currentDataExt = new CurrentDataExt();
                Channel channel = channelProcessor.findById(currentData.getChannelId() == null ? "" : currentData.getChannelId());
                Spot spot = spotProcessor.findById(currentData.getSpotId() == null ? "" : currentData.getSpotId());
                Device device = deviceProcessor.findById(currentData.getDeviceId() == null ? "" : currentData.getDeviceId());
                currentDataExt.setId(currentData.getId());
                currentDataExt.setAlarm(1);
                currentDataExt.setUnit(currentData.getUnit());
                currentDataExt.setValues(currentData.getValues());
                currentDataExt.setShowValue(currentData.getShowValue());
                currentDataExt.setUpdateTime(currentData.getCreatedTime());
                if (null != channel) {
                    currentDataExt.setChannelName(channel.getName() == null ? "" : channel.getName());
                    currentDataExt.setChannelCode(channel.getChannelCode() == null ? "" : channel.getChannelCode());
                    currentDataExt.setChannelId(channel.getId() == null ? "" : channel.getId());
                    currentDataExt.setDataType(channel.getDataType());
                } else {
                    continue;
                }
                if (null != spot) {
                    currentDataExt.setSpotName(spot.getName() == null ? "" : spot.getName());
                    currentDataExt.setSpotParentId(spot.getParentId() == null ? "" : spot.getParentId());
                    currentDataExt.setSpotId(spot.getId() == null ? "" : spot.getId());
                }
                if (null != device) {
                    currentDataExt.setDeviceName(device.getName() == null ? "" : device.getName());
                    currentDataExt.setDeviceCode(device.getDeviceCode() == null ? "" : device.getDeviceCode());
                    currentDataExt.setDeviceId(device.getId() == null ? "" : device.getId());
                }
                resultList.add(currentDataExt);
            }
        }
        return resultList;
    }

    /**
     * 扩展请求
     *
     * @param request
     * @return
     */
    public PageRespDto<CurrentDataExt> requestPageExt(CurrentDataExt request) {
        PageInfo pageInfo = request.getPageInfo();
        //设置排序
        pageInfo.setOrder("ASC");
        pageInfo.setOrderField("convert(c.channel_code,SIGNED)");
        PageRespDto<CurrentDataExt> pageResp = new PageRespDto();
        if (null != request.getAlarm()
                && 1 == request.getAlarm()
                && null != request.getDeviceId()
                && !"".equals(request.getDeviceId())) {
            List<CurrentDataExt> alarmList = this.getAlarmList(request);
            if (!CollectionUtils.isEmpty(alarmList)) {
                System.out.println(alarmList.size());
                Collections.sort(alarmList);
                List<CurrentDataExt> resultList = MyPageUtils.startPage(alarmList, pageInfo.getPageIndex(), pageInfo.getPageSize());
                pageResp.setDataList(resultList);
                pageResp.setTotal(alarmList.size());
                pageResp.setPageSize(pageInfo.getPageSize());
            } else {
                pageResp.setPageNum(1);
            }
        } else if (null != request.getDeviceId()
                && !"".equals(request.getDeviceId())) {
            Page<CurrentDataExt> page = this.service.requestPageExt(request);
            if (page != null) {
                List<CurrentDataExt> currentDataExtList = page.getResult();
                for (CurrentDataExt currentDataExt : currentDataExtList) {
                    //拉取缓存,获得最新数据
                    CurrentData currentData = currentDataCache.getCurrentdatadetails(currentDataExt.getDeviceCode() == null ? "" : currentDataExt.getDeviceCode(),
                            currentDataExt.getChannelCode() == null ? "" : currentDataExt.getChannelCode());
                    if (null != currentData) {
                        Channel channel = channelProcessor.findById(currentData.getChannelId() == null ? "" : currentData.getChannelId());
                        Spot spot = spotProcessor.findById(currentData.getSpotId() == null ? "" : currentData.getSpotId());
                        Device device = deviceProcessor.findById(currentData.getDeviceId() == null ? "" : currentData.getDeviceId());
                        if (null != channel) {
                            currentDataExt.setChannelName(channel.getName() == null ? "" : channel.getName());
                            currentDataExt.setChannelCode(channel.getChannelCode() == null ? "" : channel.getChannelCode());
                            currentDataExt.setChannelId(channel.getId() == null ? "" : channel.getId());
                        }
                        if (null != spot) {
                            currentDataExt.setSpotName(spot.getName() == null ? "" : spot.getName());
                            currentDataExt.setSpotParentId(spot.getParentId() == null ? "" : spot.getParentId());
                            currentDataExt.setSpotId(spot.getId() == null ? "" : spot.getId());
                        }
                        if (null != device) {
                            currentDataExt.setDeviceName(device.getName() == null ? "" : device.getName());
                            currentDataExt.setDeviceCode(device.getDeviceCode() == null ? "" : device.getDeviceCode());
                            currentDataExt.setDeviceId(device.getId() == null ? "" : device.getId());
                        }
                        currentDataExt.setShowValue(currentData.getShowValue() == null ? "" : currentData.getShowValue());
                        currentDataExt.setValues(currentData.getValues());
                        currentDataExt.setUnit(currentData.getUnit());
                        currentDataExt.setUpdateTime(currentData.getCreatedTime());
                        currentDataExt.setAlarm(currentData.getAlarm());
                    }
                }
                BeanUtils.copyProperties(page, pageResp);
                if (!CollectionUtils.isEmpty(page.getResult())) {
                    pageResp.setDataList(MES2RS(page.getResult()));
                }
            }
        }
        return pageResp;
    }

    private List<CurrentDataExt> MES2RS(List<CurrentDataExt> es) {
        List<CurrentDataExt> res = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(es)) {
            res.addAll(es);
        }
        return res;
    }

    @CacheEvict(value = "currentdatadetails", key = "#data.deviceCode.concat('-').concat(#data.channelCode)")
    public boolean remove(CurrentData data) {
//        currentDataCache.removeCache(data.getDeviceId());
        return super.removeById(data.getId());
    }

    public List<CurrentData> getByDeviceCode(String deviceCode) {
        return this.service.getCurrentDataByDeviceCode(deviceCode);
    }
}